package com.gitee.l0km.beanfilter.interceptor;

import java.lang.reflect.Method;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import com.alibaba.fastjson.serializer.JavaBeanSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.gitee.l0km.aocache.ContextHolder;
import com.gitee.l0km.aocache.ContextHolder.AocacheContext;
import com.gitee.l0km.beanfilter.core.CodecScope;
import com.gitee.l0km.beanfilter.core.Filterable;
import com.gitee.l0km.beanfilter.core.IFilterContainer;
import com.gitee.l0km.beanfilter.core.InterceptorContext;
import com.gitee.l0km.beanfilter.core.ThrowingFunction;
import com.gitee.l0km.beanfilter.core.json.FastjsonFilterableDeserializer;
import com.gitee.l0km.beanfilter.core.json.FastjsonFilterableSerializer;
import com.gitee.l0km.com4j.base.ILazyInitVariable;
import com.gitee.l0km.com4j.base.VolatileVariable;
import com.gitee.l0km.com4j.basex.annotations.ActiveOnClass;
import com.gitee.l0km.com4j.basex.annotations.ActiveOnClassSupport;

/**
 * 管理服务方法上安装的过滤器
 * @author guyadong
 *
 */
public class FilterContainerManager {
	private static final FilterContainerManager INSTANCE = new FilterContainerManager();
	private boolean enableInjectFastjson = true;
	private ILazyInitVariable<Boolean> activeFastjson = VolatileVariable.create(this::activeFastjson);
	private FilterContainerManager() {
	}
	/**
	 * 通过 {@link ActiveOnClass} 注解检查当前系统是否有FASTJSON
	 */
	private boolean activeFastjson() {
		try {
			return ActiveOnClassSupport.isActive(getClass(),"injectFastjsonIfEnable", FilterContainer.class);
		} catch (NoSuchMethodException e) {
			throw new RuntimeException(e);
		}
	}
	/**
	 * 服务方法上安装/注入过滤器<br>
	 * 运行时一个服务方法上向序列化/反序列化器注入过滤器的动作只会执行一次<br>
	 * 之后每次执行都是向线程局部变量安装过滤器。
	 * @param <E>
	 * @param method
	 * @param toSerializingFilterable
	 * @param toDeserializingFilterable
	 * @param scope 要求的过滤器作用范围
	 * @throws E
	 * @see InterceptorContext#injectFilter(IFilterContainer, ThrowingFunction, ThrowingFunction, CodecScope)
	 * @see InterceptorContext#installLocal(IFilterContainer)
	 */
	public <E extends Exception> void installIfAbsent(Method method,
			ThrowingFunction<Class<?>, Filterable, E> toSerializingFilterable, 
			ThrowingFunction<Class<?>,Filterable,E> toDeserializingFilterable, CodecScope scope) throws E{
		/** 在调用 FilterCompiler.compile 方法前获取AoCache上下文用于后面判断是否为计算调用 */
		AocacheContext context = ContextHolder.getLocalContext();
		FilterContainer installed = FilterCompiler.compile(method);
		if(context.isComputeInvocation()){
			/** 第一次调用,向序列化和反序列化器注入由ThreadLocal提供的过滤器 */
			InterceptorContext.injectFilter(installed, 
					toSerializingFilterable, 
					toDeserializingFilterable, scope);
			/** 如果当前系统没有FASTJSON则忽略 */
			if(activeFastjson.get()) {
				injectFastjsonIfEnable(installed);
			}
		}else {
			InterceptorContext.installLocal(installed);
		}
	}
	@ActiveOnClass(JSON.class)
	private void injectFastjsonIfEnable(FilterContainer container) {
		if(enableInjectFastjson) {
			InterceptorContext.injectFilter(container, 
					FastjsonInjectSupport::filterableFastjsonBeanSerializerOf, 
					FastjsonInjectSupport::filterableFastjsonBeanDeserializerOf, CodecScope.FASTJSON);
		}
	}
	public void setEnableInjectFastjson(boolean enableInjectFastjson) {
		this.enableInjectFastjson = enableInjectFastjson;
	}
	/**
	 * 清理线程局部变量
	 * @see InterceptorContext#clearLocal()
	 */
	public void clearLocal() {
		InterceptorContext.clearLocal();
	}
	public static FilterContainerManager getInstance() {
		return INSTANCE;
	}
	private static class FastjsonInjectSupport{

		/**
		 * [FASTJSON]返回指定Java Bean类型对应的支持Bean过滤接口({@link Filterable})的序列化器<br>
		 * 如果输入类型非Java Bean类型则返回 {@code null}
		 * 
		 * @param clazz
		 */
		private static Filterable filterableFastjsonBeanSerializerOf(Class<?> clazz) {
			ObjectSerializer serializer = SerializeConfig.getGlobalInstance().getObjectWriter(clazz);
			if (serializer instanceof Filterable) {
				return (Filterable) serializer;
			}
			Class<?> serializerClass = serializer.getClass();
			if (JavaBeanSerializer.class.equals(serializerClass)
					|| (serializerClass.getSimpleName().startsWith("ASMSerializer_")
							&& JavaBeanSerializer.class.equals(serializerClass.getSuperclass()))) {
				/** 如果是非定制序列化器则换为 FastjsonFilterableSerializer */
				FastjsonFilterableSerializer filterableSerializer = new FastjsonFilterableSerializer(clazz);
				SerializeConfig.getGlobalInstance().put(clazz, filterableSerializer);
				return filterableSerializer;
			}
			return null;
		}

		/**
		 * [FASTJSON]返回指定Java Bean类型对应的支持Bean过滤接口({@link Filterable})的反序列化器<br>
		 * 如果输入类型非Java Bean类型则返回 {@code null}
		 * 
		 * @param clazz
		 */
		private static Filterable filterableFastjsonBeanDeserializerOf(Class<?> clazz) {
			ObjectDeserializer deserializer = ParserConfig.getGlobalInstance().getDeserializer(clazz);
			if (deserializer instanceof Filterable) {
				return (Filterable) deserializer;
			}
			Class<?> deserializerClass = deserializer.getClass();
			if (JavaBeanDeserializer.class.equals(deserializerClass)
					|| (deserializerClass.getSimpleName().startsWith("FastjsonASMDeserializer_")
							&& JavaBeanDeserializer.class.equals(deserializerClass.getSuperclass()))) {
				/** 如果是非定制反序列化器则换为 FastjsonFilterableDeserializer */
				FastjsonFilterableDeserializer filterableDeserializer = new FastjsonFilterableDeserializer(clazz,
						false);
				ParserConfig.getGlobalInstance().putDeserializer(clazz, filterableDeserializer);
				return filterableDeserializer;
			}
			return null;
		}
		
	}
}
